/*!
 * Place holder
 * 
 * @Author hongqiang.tang
 * @Build 17/11/11
 * 
 * Demo : ------------------------------------------------------------------>>
 * 
 * 	var loading = new Loading({
 *		zIndex : 10000000,
 *	 	
 *		color : '#000',
 *		fontSize : '14px',
 *		backgroundColor : '#F7F7F7',
 *	
 *		text : 'Loading...',
 *		icon : '/resource/plugins/placeholder/loading.gif',
 *		template : '<div><img src="{icon}"/></div><span>{text}</span>',
 *		handlers : function ( item ) { 
 *			// Do your self logical things...
 *		}
 *	});
 * 
 *	loading.show( '#loading' );
 *	loading.hide( '#loading' );
 *
 * Demo : ------------------------------------------------------------------>>
 */ 
;( function ( root, factory ) {
	if ( typeof exports === 'object' && typeof module === 'object' ) {
		module.exports = factory( require( 'jquery' ), require( 'template' ) );
	} else if ( typeof define === 'function' && define.amd ) {
		define( [ 'jquery', 'template' ], factory );
	} else if ( typeof exports === 'object' ) {
		exports.PlaceHolder = factory( jQuery, template );
	} else {
		root.PlaceHolder = factory( jQuery, template );
	}
})( this, function ( $, Template ) {

	var defaults = {
		
		zIndex : 100,
		fontSize : '14px',
		color : '#737373',
		textAlign : 'center',
		background : 'inherit',

		text : 'Loading ...',
		icon : 'loading.gif',
		template : '<img width="16" style="vertical-align: middle;" src="{icon}"/> <span style="color: #737373;">{text}</span>',
		handlers : function () {}
	}, 
	
	PlaceHolder = function ( options ) { 
		this.init( options ); 
	};
    
	// Default styles
	function defaultStyle ( opts ) {
		return {
			
			// Styles of the mask.
			mask : { 
				zIndex : opts.zIndex,
			},

			// Styles of the last content wrapper.
			item : {
				color : opts.color,
				fontSize : opts.fontSize,
				textAlign : opts.textAlign
			}
		}
	}
	
	PlaceHolder.prototype = {

		/**
		 * Initialize place holder plug-in.
		 * 
		 * @param {JSON} options Plug-in options.
		 */
		init : function ( options ) {
			this.options = $.extend( true, {}, defaults, options );
			this.styles = defaultStyle( this.options );
			return this;
		},
		
		/**
		 * Change 
		 * 
		 * @param options
		 * @returns {PlaceHolder}
		 */
		change : function ( options ) {
			this.changeOptions = $.extend( true, {}, this.options, options );
			this.styles = defaultStyle( this.changeOptions );
			return this;
		},
		
		/**
		 * Display the place holder widget.
		 * 
		 * @param {jQuery|Element|Selector} selector The jQuery object or Html element or Selector string.
		 */
		show : function ( selector, callback ) {
			var styles = this.styles;
			var options = this.changeOptions || this.options;
			var mask, cell, item, parent, position, elements = new Array(), parentBackgroundColor;
			( selector instanceof jQuery ? selector : $( selector ) ).each( function () {
				
				parent = $( this );
				position = parent.css( 'position' );
				position === 'static' && parent.css( 'position', 'relative' );
				
				mask = $( '<div/>', { class : 'vii-holder-mask ' + options.type } ).css( styles.mask );
				cell = $( '<div/>', { class : 'vii-holder-cell' } );
				item = $( '<div/>', { class : 'vii-holder-item' } ).css( styles.item ).html( 
					Template.render( options.template || '', options ) 
				);
				
				if ( options.background ) {
					cell.css( 'background-color', options.background );
				} else {
					if ( ( parentBackgroundColor = parent.css( 'background-color' ) ) !== 'rgba(0, 0, 0, 0)' ) {
						cell.css( 'background', 'inherit' );
					}
				}
				
				cell.append( item );
				mask.append( cell );

				parent.append( mask );
				options.handlers && options.handlers( item );
				
				// Remember the all elements
				elements.push({ mask : mask, dom : parent, clear : position === 'static' });
				callback && callback( item );

			}).data( 'loading-elements-' + options.type, elements );
			delete this.changeOptions;
		},

		/**
		 * Destroy the place holder widget.
		 * 
		 * @param {jQuery|Element|Selector} selector The jQuery object or Html element or Selector string.
		 */
		hide : function ( selector, callback ) {
			var type = 'loading-elements-' + this.options.type;
			( selector instanceof jQuery ? selector : $( selector ) ).each( function () {
				var elements = $( this ).data( type );
				if ( elements ) {
					for ( var i = 0; i < elements.length; i ++ ) {
						( function ( element, cb ) {
							element && element.mask.fadeOut( function () {
								element.clear && element.dom.css( 'position', '' );
								element.mask.remove();
								cb && cb();
							});
						})( elements[ i ], callback );
					}
				}
			});
		}
	};
	return PlaceHolder;
});
